#ifndef __AUDIOSTREAM_INCLUDED
#define __AUDIOSTREAM_INCLUDED

namespace Audio
{
	namespace IO
	{
		class AudioFile;
	}
	
	class IAudioNode
	{
	public:
		IAudioNode():parent(NULL){}
		~IAudioNode(){}

		virtual void GetData(UINT8* buffer, UINT32 size, UINT32& read) = 0;
		

		virtual BOOL End() const = 0;
		virtual void SetParameter(UINT32 id, void* value) = 0;
		virtual void Rewind() = 0;

		void		Link(IAudioNode* p){ parent = p;}
		IAudioNode* GetFather() { return parent;}
	protected:
		IAudioNode* parent;

	};

	class SourceFileNode : public IAudioNode
	{
	public:
		SourceFileNode(IO::AudioFile* f) : file(f), pos(0){}
		
		virtual void GetData(UINT8* buffer, UINT32 size, UINT32& read);	
		virtual BOOL End() const ;
		virtual void SetParameter(UINT32 id, void* value) ;
		virtual void Rewind();

	private:
		IO::AudioFile*	file;
		UINT32			pos;
	};

	class BufferNode : public IAudioNode
	{
		BufferNode(UINT8* d, UINT32 s) : data(d), size(s), pos(0){}

		virtual void GetData(UINT8* buffer, UINT32 size, UINT32& read);	
		virtual BOOL End() const ;
		virtual void SetParameter(UINT32 id, void* value) ;
		virtual void Rewind();

	private:
		UINT8* data;
		UINT32 size;
		UINT32 pos;
	};


	struct AudioStreamCreateParameter
	{
		bool Loop;
		IO::AudioFile* File;
	};

	class AudioStream
	{
	public:		
		AudioStream()
			:root(NULL)
		{}

		virtual ~AudioStream()
		{
			IAudioNode* curr = root;
			while(curr != NULL)
			{
				IAudioNode* next = curr->GetFather();
				delete curr;
				curr = next;
			}
		}			
		void Rewind(){ root->Rewind();}
		void GetData(UINT8* buffer, UINT32 size, UINT32& read){ return root->GetData(buffer, size, read);};		
		BOOL End(){ return root->End();};

		static AudioStream* Create(const AudioStreamCreateParameter& p);

		static void Destroy(AudioStream* as);

	protected:
		IAudioNode* root;
		bool loop;
	};

	
}

#endif //__AUDIOSTREAM_INCLUDED